<template>
  <div class="min-h-screen bg-gray-50 p-4 md:p-6 lg:p-8">
    <div class="max-w-4xl mx-auto">
      <a-card title="图片拼接工具" class="mb-4">
        <div class="space-y-4">
          <!-- 拼接方向选择 -->
          <div class="flex items-center space-x-4">
            <span class="text-sm font-medium text-gray-700">拼接方向：</span>
            <a-radio-group v-model:value="direction">
              <a-radio-button value="horizontal">水平拼接</a-radio-button>
              <a-radio-button value="vertical">垂直拼接</a-radio-button>
            </a-radio-group>
          </div>

          <!-- 图片列表 -->
          <div class="space-y-2">
            <div class="flex justify-between items-center">
              <span class="text-sm font-medium text-gray-700">图片列表</span>
              <div class="space-x-2">
                <a-button size="small" @click="addImage">添加图片</a-button>
                <a-button size="small" @click="clearImages" danger>清空</a-button>
              </div>
            </div>
            <div class="grid grid-cols-2 md:grid-cols-3 gap-4">
              <div
                v-for="(image, index) in images"
                :key="index"
                class="relative border rounded-lg p-2"
              >
                <img :src="image.url" class="w-full h-32 object-contain" />
                <div class="absolute top-2 right-2 space-x-1">
                  <a-button
                    size="small"
                    shape="circle"
                    @click="moveImage(index, -1)"
                    :disabled="index === 0"
                  >
                    ↑
                  </a-button>
                  <a-button
                    size="small"
                    shape="circle"
                    @click="moveImage(index, 1)"
                    :disabled="index === images.length - 1"
                  >
                    ↓
                  </a-button>
                  <a-button
                    size="small"
                    shape="circle"
                    danger
                    @click="removeImage(index)"
                  >
                    ×
                  </a-button>
                </div>
              </div>
            </div>
          </div>

          <!-- 拼接设置 -->
          <div v-if="images.length > 1" class="space-y-4">
            <div>
              <label class="block text-sm font-medium text-gray-700">间距（像素）</label>
              <a-input-number v-model:value="spacing" :min="0" :max="100" />
            </div>
            <div>
              <label class="block text-sm font-medium text-gray-700">背景颜色</label>
              <input type="color" v-model="backgroundColor" class="h-8 w-16" />
            </div>
            <a-button type="primary" @click="joinImages" :loading="processing">
              开始拼接
            </a-button>
          </div>

          <!-- 结果预览 -->
          <div v-if="resultUrl" class="space-y-4">
            <div class="border rounded-lg p-4">
              <img :src="resultUrl" class="max-w-full mx-auto" />
              <div class="mt-4 flex justify-center">
                <a-button type="primary" @click="downloadResult">下载结果</a-button>
              </div>
            </div>
          </div>
        </div>
      </a-card>

      <!-- 使用说明 -->
      <a-card title="使用说明" class="mb-4">
        <ol class="list-decimal list-inside space-y-2 text-gray-600">
          <li>支持多张图片的水平或垂直拼接</li>
          <li>可调整图片顺序和间距</li>
          <li>支持自定义背景颜色</li>
          <li>建议上传相似尺寸的图片以获得最佳效果</li>
        </ol>
      </a-card>
    </div>

    <!-- 隐藏的文件输入 -->
    <input
      type="file"
      accept="image/*"
      multiple
      class="hidden"
      ref="fileInput"
      @change="handleFileSelect"
    />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { message } from 'ant-design-vue'

interface ImageItem {
  url: string
  width: number
  height: number
}

const fileInput = ref<HTMLInputElement | null>(null)
const direction = ref<'horizontal' | 'vertical'>('horizontal')
const images = ref<ImageItem[]>([])
const spacing = ref(10)
const backgroundColor = ref('#ffffff')
const processing = ref(false)
const resultUrl = ref('')

const addImage = () => {
  fileInput.value?.click()
}

const handleFileSelect = async (event: Event) => {
  const target = event.target as HTMLInputElement
  if (target.files) {
    const files = Array.from(target.files)
    for (const file of files) {
      if (!file.type.startsWith('image/')) {
        message.error('请只上传图片文件')
        continue
      }

      try {
        const imageItem = await loadImage(file)
        images.value.push(imageItem)
      } catch (error) {
        message.error('图片加载失败')
      }
    }
    // 清空input以允许重复选择相同文件
    target.value = ''
  }
}

const loadImage = (file: File): Promise<ImageItem> => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onload = (e) => {
      const img = new Image()
      img.onload = () => {
        resolve({
          url: e.target?.result as string,
          width: img.width,
          height: img.height
        })
      }
      img.onerror = reject
      img.src = e.target?.result as string
    }
    reader.onerror = reject
    reader.readAsDataURL(file)
  })
}

const moveImage = (index: number, direction: number) => {
  const newIndex = index + direction
  if (newIndex >= 0 && newIndex < images.value.length) {
    const temp = images.value[index]
    images.value[index] = images.value[newIndex]
    images.value[newIndex] = temp
  }
}

const removeImage = (index: number) => {
  images.value.splice(index, 1)
}

const clearImages = () => {
  images.value = []
  resultUrl.value = ''
}

const joinImages = async () => {
  if (images.value.length < 2) {
    message.error('请至少添加两张图片')
    return
  }

  processing.value = true
  try {
    const canvas = document.createElement('canvas')
    const ctx = canvas.getContext('2d')
    if (!ctx) throw new Error('无法创建画布上下文')

    // 计算画布尺寸
    let totalWidth = 0
    let totalHeight = 0
    let maxWidth = 0
    let maxHeight = 0

    images.value.forEach(img => {
      if (direction.value === 'horizontal') {
        totalWidth += img.width
        maxHeight = Math.max(maxHeight, img.height)
      } else {
        totalHeight += img.height
        maxWidth = Math.max(maxWidth, img.width)
      }
    })

    // 添加间距
    if (direction.value === 'horizontal') {
      totalWidth += spacing.value * (images.value.length - 1)
      canvas.width = totalWidth
      canvas.height = maxHeight
    } else {
      totalHeight += spacing.value * (images.value.length - 1)
      canvas.width = maxWidth
      canvas.height = totalHeight
    }

    // 设置背景色
    ctx.fillStyle = backgroundColor.value
    ctx.fillRect(0, 0, canvas.width, canvas.height)

    // 绘制图片
    let currentX = 0
    let currentY = 0

    for (const imageItem of images.value) {
      const img = new Image()
      await new Promise((resolve, reject) => {
        img.onload = resolve
        img.onerror = reject
        img.src = imageItem.url
      })

      if (direction.value === 'horizontal') {
        const y = (maxHeight - imageItem.height) / 2
        ctx.drawImage(img, currentX, y, imageItem.width, imageItem.height)
        currentX += imageItem.width + spacing.value
      } else {
        const x = (maxWidth - imageItem.width) / 2
        ctx.drawImage(img, x, currentY, imageItem.width, imageItem.height)
        currentY += imageItem.height + spacing.value
      }
    }

    resultUrl.value = canvas.toDataURL('image/png')
    message.success('拼接完成')
  } catch (error) {
    message.error('拼接失败')
  } finally {
    processing.value = false
  }
}

const downloadResult = () => {
  if (resultUrl.value) {
    const link = document.createElement('a')
    link.download = `joined-image-${Date.now()}.png`
    link.href = resultUrl.value
    link.click()
  }
}
</script> 